#include "utility.h"

Symbol* T;
List* nil;

void
init_utility ()
{
  T = new Symbol ("T");
  nil = new List ();
  indent (" ");
}

string
indent (string s)
{
  static int n;
  static string is;
  string x = "";
  if (s != "")
    {
      n = 0;
      is = s;
    }
  else
    {
      n++;
      for (int i = 0; i < n; i++)
	x += is;
    }
  return x;
}

list<string>
tokenize (string s)
{
  // ToDo: Fix this function
  //cout << "\n__tokenize (" << s << ")__\n";
  list<string> tokens;
  bool stringCapture = false, whitespace = false;
  string::size_type x = 0;
  for (int i = 0; i < s.length (); i++)
    {
      if (s[i] == '\"' && i-1 > 0 && s[i-1] != '\\')
	{
	  if (stringCapture)
	    {
	      i++;
	      //cout << "stringCapture: " << s.substr (x, i-x) << endl;
	      tokens.push_back (s.substr (x, i-x));
	      stringCapture = false;
	    }
	  else
	    stringCapture = true;
	  x = i;
	}
      else if (s[i] == ' ' || s[i] == '\t' || s[i] == '\n')
	{
	  if (!whitespace && !stringCapture)
	    tokens.push_back (s.substr (x, i-x));
	  if (!stringCapture)
	    x = i+1;
	  whitespace = true;
	}
      else
	whitespace = false;
    }
  if (!whitespace)
    tokens.push_back (s.substr (x));
  // Debug: tokens
  /*
  for (list<string>::iterator j = tokens.begin ();
       j != tokens.end (); j++)
    cout << *j << ":";
  cout << "\n__return tokens__\n";
  */
  /*
  // Modified from O'Reilly's C++ Cookbook Recipe 4.6 and 4.7
  const char* delim = " \f\n\r\t\v"; // whitespace characters
  s = s.substr (0, s.find_last_not_of (delim)+1);
  string::size_type i = 0;
  string::size_type j = s.find_first_of (delim);
  while (j != string::npos)
    {
      string temp = s.substr (i, j-i);
      cout << temp << ":";
      //if (temp.length ())
	tokens.push_back (s.substr (i, j-i+1));
      i = ++j;
      j = s.find_first_of (delim, j);
    }
  if (j == string::npos)
    tokens.push_back (s.substr (i, s.length ()));
  */
  return tokens;
}

List*
createPair (Symbol* key, Object* data)
{
  List* pair = new List ();
  pair->append (key);
  pair->append (data);
  return pair;
}

void
add (String* key, Object* data, List* env)
{
  add (createPair (new Symbol (key->value), data), env);
}

void
add (Symbol* key, Object* data, List* env)
{
  add (createPair (key, data), env);
}

void
add (List* pair, List* env)
{
  env->insert (pair);
}

Object*
get (String* key, List* env)
{
  return get (new Symbol (key->value), env);
}

Object*
get (Symbol* key, List* env)
{
  for (listIter item = env->begin (); item != env->end (); item++)
    {
      if ((*item)->type () == "List")
	{
	  List* pair = (List*)*item;
	  Object* car = (*pair)[0];
	  if (car->type () == "Symbol" && *(Symbol*)car == *key)
	    return (*pair)[1];
	}
    }
  return nil;
}
